package com.qf.rbac2202.annotation;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qf.rbac2202.sys.entity.SysDept;
import com.qf.rbac2202.sys.entity.SysRoleDept;
import com.qf.rbac2202.sys.entity.SysUser;
import com.qf.rbac2202.sys.entity.SysUserRole;
import com.qf.rbac2202.sys.service.ISysDeptService;
import com.qf.rbac2202.sys.service.ISysRoleDeptService;
import com.qf.rbac2202.sys.service.ISysUserRoleService;
import com.qf.rbac2202.utils.Constants;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
@Aspect  // 代表该类是一个 切面
public class DataFilterAspect {

    @Autowired
    ISysUserRoleService userRoleService;

    @Autowired
    ISysRoleDeptService roleDeptService;

    @Autowired
    ISysDeptService sysDeptService;

    // 定义切点，该切点切的是加了 DataFilter注解的方法
    @Pointcut("@annotation(com.qf.rbac2202.annotation.DataFilter)")
    public void pointcut(){}


    @Before("pointcut()")
    public void before(JoinPoint joinPoint){

        final MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        final Method method = signature.getMethod();
        final DataFilter annotation = method.getAnnotation(DataFilter.class);
        final String dataField = annotation.dataField();


        // 通过反射api 获取DataFilter注解中配置的 数据库 部门id对应的字段名称
        final Object[] args = joinPoint.getArgs();

        final Object arg = args[0];

        //  sql例如： dept_id in (1,2,3)
        final String deptStr = getDeptStr();

        if (deptStr==null){  // 如果是超级管理员，那么这里直接返回即可
            return;
        }

        if (deptStr.equals("()")){  // 说明当前用户没有任何数据权限
            ((Map) arg).put(Constants.DATA_FILETER,"(dept_id in (-1))");
            return ;
        }

        String sql = "("+ dataField+" in "+ deptStr +")";



        if (arg!=null && arg instanceof Map) {
            ((Map) arg).put(Constants.DATA_FILETER,sql);
        }

    }

    /**
     * 获取当前登录用户的 数据权限字符串
     * 如果是管理员，那么直接获取全部部门信息
     * 如果非管理员，只获取有权限的部门
     * @return
     */
    private String getDeptStr() {
        final Subject subject = SecurityUtils.getSubject();
        final SysUser user = (SysUser) subject.getPrincipal();

        if (user.getUserId().equals(Constants.SUPER_ADMIN_ID)){
//            final List<SysDept> deptList = sysDeptService.list();
//
//            // List<SysDept>  ---> Stream<部门ID>  ----> (1,2,3,4)
//            final String sql = deptList.stream()
////                    .map(SysDept::getDeptId)
//                    .map(dept -> dept.getDeptId() + "")
//                    .collect(Collectors.joining(",", "(", ")"));
//            return sql;
            return null;
        }

        // 根据当前登录用户查询用户的角色
        final QueryWrapper<SysUserRole> sysUserRoleQueryWrapper = new QueryWrapper<>();
        sysUserRoleQueryWrapper.select("role_id");
        sysUserRoleQueryWrapper.eq("user_id",user.getUserId());
        final List<Object> roleIdList = userRoleService.listObjs(sysUserRoleQueryWrapper);

        // 再查询该角色拥有哪些部门id
        final QueryWrapper<SysRoleDept> sysRoleDeptQueryWrapper = new QueryWrapper<>();
        sysRoleDeptQueryWrapper.select("dept_id");
        sysRoleDeptQueryWrapper.in("role_id",roleIdList);
        final List<Object> deptIdList = roleDeptService.listObjs(sysRoleDeptQueryWrapper);

        // List<部门id> ----> (1,2,3)
        final String deptStr = deptIdList.stream().map(o -> o.toString())
                .collect(Collectors.joining(",", "(", ")"));
        return deptStr;
    }

}
